﻿namespace ScrumLite.Data.Tests
{
    using System;
    using System.Text;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System.Transactions;

    /// <summary>
    /// Summary description for DefectManagerFixture
    /// </summary>
    [TestClass]
    public class DefectManagerFixture
    {
        IDefectStore store;
        private static Guid projectId = new Guid("1C4F9968-8D5E-4d8a-9BD8-9A8DF1434B5A");
        private static Guid del1 = new Guid("1C4F9968-8D5E-4d8a-9BD8-9A8DF1434AAA");
        private static Guid def1 = new Guid("BC4F9968-8D5E-4d8a-9BD8-9A8DF1434AAA");
        private static Guid def2 = new Guid("2d408e65-28fc-47ab-a82e-9d134ef81e61");

        [TestInitialize]
        public void Initialize()
        {
            store = new DefectStore();
        }

        [TestMethod()]
        public void ShouldAddNewDefect()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeDefectsStore();
                Defect d = new Defect() { createdOn=DateTime.Today, decision="", id=Guid.NewGuid(), moniker=1, notes="", severity=null , title="", triagedOn=null, user_createdBy="", fk_deliverable=del1 };
                this.store.Add(d);

                Defect[] actual = this.store.RetrieveDefects(projectId, true);
                Assert.IsNotNull(actual);
                Assert.AreEqual(4, actual.Count());
                Assert.IsTrue(actual.Contains(actual.FirstOrDefault(c => c.id == d.id)));
            }
        }

        [TestMethod()]
        public void ShouldUpdateDefect()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeDefectsStore();
                ScrumLiteDataContext context = new ScrumLiteDataContext();
                Defect d = context.Defects.FirstOrDefault();
                d.notes = "updated";
 
                this.store.Update(d);

                Defect actual = this.store.RetrieveDefect(d.id);
                Assert.IsNotNull(actual);
                Assert.AreEqual("updated", d.notes);
            }
        }

        [TestMethod()]
        public void ShouldDeleteDefect()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeDefectsStore();
                this.store.Delete(def1);
                Defect[] actual = this.store.RetrieveDefects(projectId, true);

                Assert.IsNotNull(actual);
                Assert.AreEqual(2, actual.Count());
                Assert.IsFalse(actual.Contains(actual.FirstOrDefault(c => c.id == def1)));
            }
        }

        [TestMethod()]
        public void ShouldGetDefectsById()
        {
            Defect defectExpected = new Defect() { createdOn = DateTime.Today, decision = "", id = def1, moniker = 1, notes = "", severity = null, title = "", triagedOn = null, user_createdBy = "", fk_deliverable = del1 };

            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeDefectsStore();
                Defect defect = store.RetrieveDefect(def1);

                Assert.IsNotNull(defect);
                Assert.AreEqual(defectExpected.id, defect.id);
                Assert.AreEqual(defectExpected.createdOn, defect.createdOn);
                Assert.AreEqual(defectExpected.decision, defect.decision);
                Assert.AreEqual(defectExpected.moniker, defect.moniker);
                Assert.AreEqual(defectExpected.fk_deliverable, defect.fk_deliverable);
            }
        }

        [TestMethod()]
        public void ShouldGetDefectsNotTriaged()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeDefectsStore();
                Defect[] defect = store.RetrieveDefects(projectId,false);

                Assert.IsNotNull(defect);
                Assert.AreEqual(2, defect.Count());
                Assert.AreEqual(1, defect.Where(d => d.id == def1).Count());
                Assert.AreEqual(1, defect.Where(d => d.id == def2).Count());
                Assert.AreEqual(2, defect.Where(d => d.triagedOn == null).Count());
            }
        }

        [TestMethod()]
        public void ShouldGetDefectsByProjectIdAndMoniker()
        {
            Defect defectExpected = new Defect() { createdOn = DateTime.Today, decision = "", id = def2, moniker = 2, notes = "", severity = null, title = "", triagedOn = null, user_createdBy = "", fk_deliverable = del1};

            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeDefectsStore();
                Defect defect = store.RetrieveDefect(projectId.ToString(), 2);

                Assert.IsNotNull(defect);
                Assert.AreEqual(defectExpected.id, defect.id);
                Assert.AreEqual(defectExpected.createdOn, defect.createdOn);
                Assert.AreEqual(defectExpected.decision, defect.decision);
                Assert.AreEqual(defectExpected.moniker, defect.moniker);
                Assert.AreEqual(defectExpected.fk_deliverable, defect.fk_deliverable);
            }
        }

        [TestMethod()]
        public void ShouldReturnLastMoniker()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeDefectsStore();
                int moniker = store.RetrieveLastMoniker(projectId);

                Assert.AreEqual(3, moniker);
            }
        }

        private static void CreateFakeDefectsStore()
        {

            using (ScrumLiteDataContext context = new ScrumLiteDataContext())
            {
                Project project = new Project() { endsOn = DateTime.Today, id = projectId, name = "FakeProject", security_group = "", startsOn = DateTime.Today, uri_repository = "", user_ownedBy = "" };
                context.Projects.InsertOnSubmit(project);

                Deliverable deliverable1 = new Deliverable() { fileName = "test", id = del1, moniker = 1, pk_project = projectId, releasedOn = DateTime.Now, uri_repository = "" };
                context.Deliverables.InsertOnSubmit(deliverable1);

                Defect defect1 = new Defect() { createdOn = DateTime.Today, decision = "", id = def1, moniker = 1, notes = "", severity = null, title = "", triagedOn = null, user_createdBy = "", fk_deliverable = deliverable1.id };
                Defect defect2 = new Defect() { createdOn = DateTime.Today, decision = "", id = def2, moniker = 2, notes = "", severity = null, title = "", triagedOn = null, user_createdBy = "", fk_deliverable = deliverable1.id };
                Defect defect3 = new Defect() { createdOn = DateTime.Today, decision = "", id = Guid.NewGuid(), moniker = 3, notes = "", severity = null, title = "", triagedOn = DateTime.Today, user_createdBy = "", fk_deliverable = deliverable1.id };
                context.Defects.InsertOnSubmit(defect1);
                context.Defects.InsertOnSubmit(defect2);
                context.Defects.InsertOnSubmit(defect3);

                context.SubmitChanges();
            }
        }
    }
}
